home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000 #2
/
Ham Radio 2000 - Volume 2.iso
/
HAMV2
/
TCP_IP
/
TNOS230S
/
XFWD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-08-18
|
30KB
|
985 lines
/* Derived from fbbfwd.c */
#include "global.h"
#ifdef XFWD
#include "ctype.h"
#include "commands.h"
#include "files.h"
#include "bm.h"
#include "reject.h"
#if !defined(_lint)
static char rcsid[] OPTIONAL = "$Id: xfwd.c,v 1.22 1997/08/19 01:19:22 root Exp root $";
#endif
extern int MbForwarded, SYSOPprotect;
extern int FWDpersonal, FWDbulletins;
extern char FWDCall[AXALEN];
extern int indexFwdBbs (char *name);
extern void importcmd (int mode, char *bbsname);
extern int bid_check (register char *string);
extern char *nntp_name_expansion (char *name);
extern void exitfwd (struct mbx *m);
static int xdosy (struct fbbpacket *msglst,struct fwd *f,int msgcnt);
static int doxrecv (struct fwd *f);
static int doxsend (struct fwd *f, int firstsend);
static int xfwdthisarea (struct fwd *, char *, int *, int *);
static void sendEndOfXBlock (struct fwd *, int, int *, int *);
#ifdef CATALOG
#include "catalog.h"
#define CAT xfwd_catalog
#define forwardingto __STR(0)
#define nodatatosend __STR(1)
#define closingfwdfile __STR(2)
#define processingarea __STR(3)
#define sendingto __STR(4)
#define sendingSXto __STR(5)
#define badSY __STR(6)
#define lostremote __STR(7)
#define receivedSYfrom __STR(8)
#define transferfailed __STR(9)
#define errorgettingtemp __STR(10)
#define errorxdosycode __STR(11)
#define sendingmessageto __STR(12)
#define refusing __STR(13)
#define mailrefused __STR(14)
#define transfersuccess __STR(15)
#define mailsent __STR(16)
#define receivecode __STR(17)
#define sendingSY __STR(18)
#define messagesreceived __STR(19)
#define receivedfrom __STR(20)
#else /* CATALOG */
static const char forwardingto[] = "%sing X-forwarding of PBBS mail to: %s ";
static const char nodatatosend[] = "XFWD: No Data to send. Sending F> to %s\n";
static const char closingfwdfile[] = "XFWD: Closing .fwd file for %s.\n";
static const char processingarea[] = "XFWD: Processing %s message area %s for %s.\n";
static const char sendingto[] = "XFWD: Sending ( to %s ) to %s";
static const char sendingSXto[] = "XFWD: Sending SX Block of %d to %s\n";
static const char badSY[] = "XFWD Error: Expected 'SY ' string. Received '%s' string";
static const char lostremote[] = "XFWD: Lost the remote connection with %s...\n";
static const char receivedSYfrom[] = "XFWD: Received '%s' from %s\n";
static const char transferfailed[] = "XFWD: Transfer failed with %s......\n";
static const char errorgettingtemp[] =
"XFWD: Error getting tmp file.\n"
"XFWD: We're going to pass this file to sendmsg()\n"
"XFWD: We were trying to open %s and failed.\n";
static const char errorxdosycode[] = "XFWD: Error opening %s in xdosy() code.\n";
static const char sendingmessageto[] = "XFWD: Sending message to %s\n";
static const char refusing[] = "XFWD: Skipping message %s refused\n";
static const char mailrefused[] = "XFWD: bbs mail refused: %s from %s";
static const char transfersuccess[] = "XFWD: Transfer successful with %s\n";
static const char mailsent[] = "PBBS mail sent: %s ";
static const char receivecode[] = "XFWD: This is the receive code for %s.\n";
static const char sendingSY[] = "XFWD: Sending our 'SY %d' response to %s.\n";
static const char messagesreceived[] = "XFWD: Messages received (%d) from %s....\n";
static const char receivedfrom[] = "XFWD: Received from %s - %s\n";
#endif /* CATALOG */
/* This code processes a SY packet from a remote system.
Return = 0 means an error was detected.
1 means an 'F>' or '>' was received from the remote system.
2 means an 'Fx' (where x is something) was received.
*/
static int xdosy (msglst, f, msgcnt)
struct fbbpacket *msglst;
struct fwd *f;
int msgcnt;
{
int i, k;
struct mbx *m;
int incnt;
char txtfile[80], *cp, *cp2;
char tmp[AXBUF];
m = f->m;
/* Send any data in our buffer. */
usflush (m->user);
eatprompt:
/* Get the SY line. */
if (recvline (m->user, (unsigned char *)m->line, MBXLINE) == -1 ) {
if (Xtrace)
tcmdprintf (lostremote, fwd_bbsname(m));
return 0;
}
/* remove any line-end characters. */
rip (m->line);
if (Xtrace)
tcmdprintf (receivedSYfrom, m->line, fwd_bbsname(m));
/* Make sure we got a "SY " line. Anything else is an error. */
if (strnicmp (m->line, "SY ", 3) != 0) {
if (!m->fwdbbs->eatenanyprompts && !strcmp (">", m->line)) {
m->fwdbbs->eatenanyprompts = 1;
tcmdprintf ("XFWD: Eating a stray '>' (only allowed once) for %s\n", fwd_bbsname(m));
goto eatprompt;
}
tprintf (badSY, m->line);
tputs (".\n");
if (Xtrace) {
tcmdprintf(badSY, m->line);
tcmdprintf(" from %s\n", fwd_bbsname(m));
}
return 0;
}
m->fwdbbs->eatenanyprompts = 1;
incnt = atoi (&m->line[3]);
/* Check to see if we got too many responses. */
/* The next check makes sure we got enough of the right responses. */
if(incnt > msgcnt)
return 0;
/* Validate SY line. Clean up unused entries. */
for (i = 0; i < XMAXMSGS; i++) {
msglst[i].accept = fbbNO;
if (i >= msgcnt) {
/* Zero out and free rest of the FS structure. */
free (msglst[i].to);
msglst[i].to = NULLCHAR;
free (msglst[i].from);
msglst[i].from = NULLCHAR;
free (msglst[i].messageid);
msglst[i].messageid = NULLCHAR;
free (msglst[i].sline);
msglst[i].sline = NULLCHAR;
}
}
/* process the requested bid in the SY block */
for (i = 0; i < incnt; i++) {
if (recvline (m->user, (unsigned char *)m->line, MBXLINE) == -1) {
if (Xtrace)
tcmdprintf (transferfailed, fwd_bbsname(m));
return 0;
}
rip (m->line);
for (k = 0; k < msgcnt; k++) {
if (!stricmp (m->line, msglst[k].bid)) {
msglst[k].accept = fbbYES;
break;
}
}
}
/* Now open the tempfile */
(void) tmpnam (txtfile);
if ((m->quickfile = fopen (txtfile, "w+b")) == NULLFILE) {
tcmdprintf (errorgettingtemp, txtfile);
if (Xtrace)
log (m->user, errorxdosycode, txtfile);
return 0;
}
/* The SY line is OK. Send the requested messages. */
for (i = 0; i < msgcnt; i++) {
kwait (NULL);
MbForwarded++;
if(msglst[i].accept == fbbYES) {
/* Message is wanted. We need to send it.
Do not update the X-Forwarded Header yet. X-fwd does not tell us
if it received the message or not. We have to send all our
messages and then see if the connect is still there. If we get
a valid FBB Response, then we can assume that the messages were
delivered and update the X-Forwarded flag. */
if (Xtrace)
tcmdprintf (sendingmessageto, fwd_bbsname(m));
changearea (f->m, msglst[i].area, (int) 0);
/* build From: line */
strncpy (m->line, msglst[i].sline, MBXLINE);
cp = strchr (m->line, '<');
if (cp == NULLCHAR) /* shouldn't ever happen */
continue;
cp += 2;
cp2 = strchr (cp, ' ');
if (cp2 != NULLCHAR) /* also shouldn't ever happen */
*cp2 = 0;
fprintf (m->quickfile, "%s%s", Hdrs[FROM], cp);
strncpy (m->line, msglst[i].bid, MBXLINE);
cp = strpbrk (m->line, "_-");
if (cp) {
*cp = '@';
fprintf (m->quickfile, "%s", cp);
}
/* build Message-Id: line */
fprintf (m->quickfile, "\n%s<%lu@%s>\n", Hdrs[MSGID], m->mbox[msglst[i].number].bid,
(*FWDCall) ? pax25(tmp,FWDCall) : pax25(tmp,Mycall));
/* build To: line */
strncpy (m->line, msglst[i].sline, MBXLINE);
cp = strchr (&m->line[3], '@');
if (cp == NULLCHAR) {
cp = strchr (&m->line[3], ' ');
if (cp != NULLCHAR)
*cp = 0;
fprintf (m->quickfile, "%s%s\n", Hdrs[TO], &m->line[3]);
} else {
*cp = 0;
if (*(cp-1) == ' ')
*(cp-1) = 0;
if (*++cp == ' ')
++cp;
cp2 = strchr (cp, ' ');
if (cp2 != NULLCHAR)
*cp2 = 0;
fprintf (m->quickfile, "%s%s@%s\n", Hdrs[TO], &m->line[3], cp);
}
/* now the msgtype line */
fprintf (m->quickfile, "%s%c\n", Hdrs[MSGTYPE], msglst[i].sline[1]);
/* and the X-BID line */
if (msglst[i].sline[1] == 'B' || ((msglst[i].sline[1] == 'P') && (!stricmp (msglst[i].area, "sysop") || !stricmp (&m->line[3], "sysop"))))
fprintf (m->quickfile, "%s%s\n", Hdrs[XBID], msglst[i].bid);
/* and finally the subject */
fprintf (m->quickfile, "%s%s\n\n", Hdrs[SUBJECT], msglst[i].subject);
/* Prepare the text of the message. */
sendmsg(f->m, msglst[i].number, msglst[i].bid);
fprintf (m->quickfile, "/EX\n");
f->sentThisArea++;
} else {
/* The remote system does not want this message.
Go ahead and mark the msg as so. If the link goes
down, we still want to mark this message as unwanted.
One the link goes back up, we do not want to ask the
remote system again about this because it already
told us no. */
if (Xtrace)
tcmdprintf (refusing, fwd_bbsname(m));
/* mark message as forwarded or deleted. */
mark_forwarded (msglst[i].fwdfile, msglst[i].fwdfileindex, '*');
m->change |= CHG_READ;
log (m->user, mailrefused, msglst[i].sline, fwd_bbsname(m));
}
}
/* close the file. send_lzhuf() will re-open it. */
(void) fclose (m->quickfile);
m->quickfile = NULLFILE;
/* And Send it. */
if (incnt)
(void) send_lzhuf(f, txtfile);
else
unlink (txtfile);
/* Now we will get a line from the remote system to make sure that the
messages were received ok. */
usflush (m->user);
if (recvline (m->user, (unsigned char *)m->line, MBXLINE) == -1) {
/* There was a problem. We did not get a response from the remote
system after we sent our messages. */
if (Xtrace)
tcmdprintf (transferfailed, fwd_bbsname(m));
return 0;
} else if (toupper(*m->line) == 'F' || *m->line == '>'){ /* only mark completed, if no garbage came in */
if (Xtrace)
tcmdprintf (transfersuccess, fwd_bbsname(m));
/* We got a response back, so we can update our sent and unwanted messages. */
for (i = 0; i < msgcnt; i++) {
if (msglst[i].accept == fbbYES) {
/* mark message as sent. */
mark_forwarded (msglst[i].fwdfile, msglst[i].fwdfileindex, '*');
m->change |= CHG_READ;
log (m->user, mailsent, msglst[i].sline);
#ifdef STATS_MSG
STATS_addmsg(1, 1);
#endif
#ifdef STATS_TFC
STATS_addtfc(3, 1);
#endif
#ifdef STATS_FWD
STATS_addfwd(1, 1, m->name);
#endif
}
if((!isarea (msglst[i].area) || msglst[i].type != 'B') && (stricmp(msglst[i].area, "sysop") || !SYSOPprotect)) {
m->mbox[msglst[i].number].status |= BM_DELETE;
statusCtl (msglst[i].area, "ctl", &m->mbox[msglst[i].number], msglst[i].number, 0);
m->change |= CHG_DELETE;
}
free (msglst[i].to);
msglst[i].to = NULLCHAR;
free (msglst[i].from);
msglst[i].from = NULLCHAR;
free (msglst[i].messageid);
msglst[i].messageid = NULLCHAR;
free (msglst[i].sline);
msglst[i].sline = NULLCHAR;
}
}
if (strnicmp (m->line,"F>", 2) == 0 || *m->line == '>')
return 1;
else
return 2;
}
/* returns 0 = okay, 1 = aborted, 2 = invalid data, 3 = lost connection, 4 = recv 'F>' */
static int doxrecv(struct fwd *f)
{
int msgsize = 0;
int i, k;
char tempname[80], *cp;
struct fbbpacket *msglst;
struct mbx *m;
int incnt = 0, mycnt = 0;
int16 inchecksum, mychecksum;
int retval = 0;
#ifdef REJECT
int rej;
#endif
msglst = f->msglst;
m = f->m;
if (Xtrace)
tcmdprintf (receivecode, fwd_bbsname(m));
if (!f->numtrans) {
if (recvline (m->user, (unsigned char *)m->line, MBXLINE) == -1) {
if (Xtrace)
tcmdprintf (lostremote, fwd_bbsname(m));
return 3;
}
rip (m->line);
if (Xtrace)
tcmdprintf (receivedfrom, fwd_bbsname (m), m->line);
(void) strupr(m->line);
if (!strnicmp ("F>", m->line, 2))
return 4;
if (strnicmp ("SX ", m->line, 3))
return 2;
incnt = atoi (&m->line[3]);
} else {
incnt = f->numtrans;
f->numtrans = 0;
}
for (i = 0; i < XMAXMSGS; i++)
msglst[i].accept = fbbNO;
/* Loop till we have received a all X blocks. */
for (k = 0; k < incnt; k++) {
if (recvline (m->user, (unsigned char *)m->line, MBXLINE) == -1) {
if (Xtrace)
tcmdprintf (lostremote, fwd_bbsname(m));
return 3;
}
kwait (NULL);
if (cutofffwding (m))
return 3;
/* strip any trailing NL characters. */
rip(m->line);
if (Xtrace)
tcmdprintf (receivedfrom, fwd_bbsname(m), m->line);
log (m->user, "XFWD %s: %s", fwd_bbsname(m), m->line);
#ifdef REJECT
rej = reject (m->line, 1, 1);
if (rej != REJ_REJECT && rej != REJ_DEFER)
#endif
if (!bid_check (m->line))
strncpy (msglst[mycnt++].bid, m->line, 15);
}
if (Xtrace)
tcmdprintf (sendingSY, mycnt, fwd_bbsname(m));
tprintf ("SY %d\n", mycnt);
for (k = 0; k < mycnt; k++)
tprintf ("%s\n", msglst[k].bid);
usflush(m->user);
if (mycnt) {
/* receive the SS block, with the compressed data size */
if (recvline (m->user, (unsigned char *)m->line, MBXLINE) == -1) {
if (Xtrace)
tcmdprintf (lostremote, fwd_bbsname(m));
return 3;
}
if (Xtrace)
tcmdprintf (receivedfrom, fwd_bbsname(m), m->line);
msgsize = atoi (&m->line[3]);
cp = skipnonwhite (&m->line[3]);
cp = skipwhite (cp);
inchecksum = (int16) atol (cp);
/* The remote system will start sending the message data. */
/* Set up a temp name to receive the file. */
sprintf (tempname, "%s/%s.imp", IMPORTDir, m->name);
/* Receive the messages and uncompress them. */
strncpy (f->iFile, tmpnam(NULL), FWDFILELEN);
strncpy (f->oFile, tempname, FWDFILELEN);
if (recv_lzhuf(f, msgsize, &mychecksum) == 0)
return 1;
if (inchecksum != mychecksum) {
if (Xtrace)
tcmdprintf ("XFWD: Checksum error with %s: received %u, calculated %u\n", fwd_bbsname(m), inchecksum, mychecksum);
retval = 1;
unlink (f->oFile);
} else
importcmd (0, m->name);
/* remove the other file */
unlink (f->iFile);
if (Xtrace && !retval)
tcmdprintf (messagesreceived, mycnt, fwd_bbsname(m));
}
return retval;
}
/****************************************************************************************/
/* This code is called when we've 25 X-Blocks, or we don't have any more */
/* messages to send. */
/****************************************************************************************/
static void sendEndOfXBlock (f, msgcnt, Xok, Xdone)
struct fwd *f;
int msgcnt, *Xok, *Xdone;
{
int rc;
struct mbx *m;
struct fbbpacket *msglst;
/* point pointers to their proper location. */
msglst = f->msglst;
m = f->m;
if (Xtrace)
tcmdprintf (sendingSXto, msgcnt, fwd_bbsname(m));
tprintf ("SX %d\n", msgcnt);
for (rc = 0; rc < msgcnt; rc++)
tprintf ("%s\n", msglst[rc].bid);
/* Process an incoming SY and receive messages. */
rc = xdosy(msglst, f, msgcnt);
if (!rc) {
*Xok = FALSE;
*Xdone = TRUE;
} else if (rc == 1) {
*Xok = TRUE;
*Xdone = FALSE;
} else if (rc == 2) {
*Xok = TRUE;
*Xdone = TRUE;
}
}
/****************************************************************************************/
/* This code is called for each message area we forward to. */
/****************************************************************************************/
static int xfwdthisarea (f, area, Xok, Xdone)
struct fwd *f;
char *area;
int *Xok, *Xdone;
{
char line[MBXLINE];
int err = 0;
int msgcnt = 0;
int Tmsgcnt = 0;
int theindex = 0;
int changed = 0;
int rc, i;
long bid;
long curpos;
long tempsize;
char *pszBid;
long msgsize = 0;
#if 0
int passes = 0;
#endif
struct let *cmsg;
struct mbx *m;
struct fbbpacket *msglst;
/* for makecl() */
int bulletin;
char *newto = NULLCHAR;
char line2[64];
char thebid[LINELEN];
char subject[LINELEN];
struct arealist *a;
/* point pointers to their proper location. */
msglst = f->msglst;
m = f->m;
/* public area? */
bulletin = isarea (area);
if (Xtrace && FWDareatrace)
tcmdprintf (processingarea, bulletin ? "Public " : "Private ", area, fwd_bbsname(m));
/* Initialize variables. */
*Xok = TRUE;
*Xdone = FALSE;
if (bulletin && (!FWDbulletins || !m->fwdbbs->bulletins)) {
if (Xtrace)
tcmdprintf ("Skipping any bulletins in area '%s' for %s\n", area, m->fwdbbs->name);
return Tmsgcnt;
}
if (!bulletin && (!FWDpersonal || !m->fwdbbs->personals)) {
if (Xtrace)
tcmdprintf ("Skipping any personal messages in area '%s' for %s\n", area, m->fwdbbs->name);
return Tmsgcnt;
}
/* check if there are any messages in this area that need to be forwarded. */
rewind (f->fwdfile); /* rewind forward file... */
curpos = 0L; /* set file position */
/* read each line in the .fwd file. exit loop on error or no more lines */
while (!err && fgets (line, MBXLINE, f->fwdfile) != NULLCHAR) {
(void) fflush (f->fwdfile);
kwait (NULL); /* Give control back to system. */
if (*line != '*' && *line != '!' && *line != '-') { /* '*' means this has been done */
/* '!' means this is blocked */
/* '-' means this was sent to an ALT BBS */
if ((pszBid = strpbrk(&line[1], " \t")) != NULLCHAR) /* get the bid. */
*pszBid++ = '\0';
else
continue; /* improperly formatted */
if (!stricmp (area, &line[1])) { /* is this the correct area? */
bid = atol (pszBid); /* get the message number */
if (!changed) { /* are we in the right area... */
m->area[0] = 0; /* force a reload of index */
changearea(m, area, (int) 0); /* if not... go there now... */
changed = 1; /* and update the flag....*/
}
/* Set the 'found message flag' to false. */
theindex = 0;
/* for each message in the .txt file... */
for (cmsg = &m->mbox[1], i = 1; i <= m->nmsgs; i++, cmsg++)
/* find the message we're supposed to forward. */
if ((bid == cmsg->bid) && !(cmsg->status & BM_DELETE)) {
/* this is the message... set the flag and break. */
theindex = i;
break;
}
if (theindex && m->fwdbbs && m->fwdbbs->maxsize && cmsg->size > m->fwdbbs->maxsize) {
if (Xtrace)
tcmdprintf ("XFWD: Deferring large message to %s, allowed=%ld, size=%ld\n", m->fwdbbs->name, m->fwdbbs->maxsize, cmsg->size);
} else {
/* if we didn't find the message... it must have been deleted. We can */
/* mark the message as forwarded so we don't try it again. This is just */
/* done for performance reasons. */
/* Also, if found, block it. Then if an I/O error occurs, this message */
/* will be skipped until all others have a chance to get passed */
mark_forwarded (f->fwdfile, curpos, (!theindex) ? '*' : '!');
/* if the 'found message flag' is set.... */
if (theindex && !(cmsg->status & (BM_ONHOLD | BM_DELETE))) {
newto = NULLCHAR; /* just in case */
if (m->fwdbbs) /* just in case */
for (a = m->fwdbbs->areas; a; a = a->next)
if (!stricmp (area, a->name))
newto = a->forceaddr;
/* Prepare the FB line. */
bulletin = isarea (area); /* reset, just in case */
rc = makecl(m, theindex, newto, line2, subject, thebid, &bulletin);
if (rc == -2) { /* delete the message */
mark_forwarded (f->fwdfile, curpos, '*');
if ((!isarea (area) || m->stype != 'B') && (stricmp (area, "sysop") || !SYSOPprotect)) {
m->mbox[i].status |= BM_DELETE;
statusCtl (area, "ctl", &m->mbox[i], i, 0);
m->change |= CHG_DELETE;
}
} else if (rc != -1) { /* If command line ok, store it. */
/* Copy SEND line for message log. */
free (msglst[msgcnt].sline);
(void) strupr (msglst[msgcnt].sline = strdup (line2));
msglst[msgcnt].fwdfileindex = curpos;
msglst[msgcnt].fwdfile = f->fwdfile;
/* store the message type */
msglst[msgcnt].type = msglst[msgcnt].sline[1];
/* Keep track of the subject. */
free (msglst[msgcnt].subject);
msglst[msgcnt].subject = strdup (subject);
/* Keep track of the message area */
free (msglst[msgcnt].area);
msglst[msgcnt].area = strdup (area);
/* Keep track of message number in area. */
msglst[msgcnt].number = i;
/* Keep track of makecl() modified bid. */
strncpy (msglst[msgcnt].bid, &thebid[1], 15);
if (Xtrace)
tcmdprintf (sendingto, fwd_bbsname(m), line2);
msgcnt++;
msgsize += m->mbox[theindex].size;
/* If we have filled our SX Block */
if (msgcnt >= XMAXMSGS || (m->fwdbbs && m->fwdbbs->fbbsize && msgsize > m->fwdbbs->fbbsize)) {
sendEndOfXBlock (f, msgcnt, Xok, Xdone);
Tmsgcnt += msgcnt;
msgcnt = 0;
msgsize = 0;
}
}
}
}
}
} /* end if() */
/* If we got an error from dofs() or the response
from dofs() was 2, we are done with this message
transfer. If we got a 1 from dofs() we can send
more messages now so we do not need to exit. */
if (*Xdone)
break;
curpos = ftell (f->fwdfile); /* get file position */
tempsize = m->mysize;
if(isnewprivmail (m, "fwd") > 0) {
m->mysize = tempsize;
break;
}
} /* end while() */
/* If we have any left over messages... send them now. */
if (msgcnt) {
sendEndOfXBlock (f, msgcnt, Xok, Xdone);
Tmsgcnt += msgcnt;
}
return Tmsgcnt;
}
/* This code is used to figure out what messages need to be sent. */
static int doxsend (f, firstsend)
struct fwd *f;
int firstsend;
{
int err = 0;
int Tmsgcnt;
int Xdone;
int Xok = 0;
long pos;
char name[256];
struct arealist *fwdarea;
struct mbx *m;
int areasused;
int equals, bang;
/* point pointers to their proper location. */
m = f->m;
/* figure out name of the user. */
sprintf (name, "%s/%s", Mailspool, m->name);
(void) nntp_name_expansion (name);
/* Save data */
strncpy (f->savefsline, m->line, MBXLINE);
/* figure out .fwd file name and see if it exist. It it doesn't exist... */
/* .... we have nothing for this user. */
strcat (name, ".fwd");
(void) strlwr (name);
if ((f->fwdfile = fopen (name, UPDATE_TEXT)) == NULLFILE)
/* the file doesn't exist. This should only occur with a reverse forward request. */
return 2;
/* Check to see if we have any info to send and make sure it is the
right time to send data. */
if (!f->m->fwdbbs && fwdinit (f->m, 1) == -1)
/* The bbs is not in the forward.bbs file or it is the wrong time to send.
Return a 0 to indicate that we have no data for the remote system. */
return 0;
/* Now grab a subchannel slot, if needed. It is available, or fwdinit()
would have returned -1. */
(void) checksubchannel (m, 1);
/* restore data. */
strncpy(m->line, f->savefsline, MBXLINE);
checkloop:
kwait (NULL);
/* Initialize the fwdarea pointer. This is the list of areas we forward to. */
fwdarea = m->fwdbbs->areas;
/* for each area in the fwdarea list do.... */
err = 0;
Tmsgcnt = 0;
areasused = 0;
(void) isnewprivmail (m, "fwd"); /* first time, just sets m->mysize */
while (!err && fwdarea) {
kwait (NULL);
if (cutofffwding (m)) {
Xok = 0;
break;
}
f->sentThisArea = 0;
Tmsgcnt += xfwdthisarea (f, fwdarea->name, &Xok, &Xdone);
if (Xdone || Tmsgcnt)
break;
if (isnewprivmail (m, "fwd") > 0)
goto checkloop;
if (f->sentThisArea) /* if we got something in this area */
areasused += 1;
fwdarea = fwdarea->next; /* Do next area. */
} /* end while() */
if (!Xok) { /* We had an error. */
(void) fclose (f->fwdfile);
return 3;
}
/* this next piece (and the sections above that affect areasused), make
this go BACK to check for messages added into earlier areas. This
prevents us from disconnecting if some new info JUST came in. */
if (areasused)
goto checkloop;
if (Xtrace)
tcmdprintf (closingfwdfile, fwd_bbsname(m));
/* See if we can remove the .fwd file. */
fwdlockit (m->name);
rewind (f->fwdfile);
equals = 0;
bang = 0;
while (pos = ftell (f->fwdfile), fgets (f->line, MBXLINE, f->fwdfile) != NULLCHAR) {
kwait (NULL);
if (*f->line == '=') {
mark_forwarded(f->fwdfile, pos, '!');
equals++;
err = 1;
} else if (*f->line == '!') {
mark_forwarded(f->fwdfile, pos, ' ');
bang++;
err = 1;
} else if(*f->line != '*' && *f->line != '-') { /* if not already done */
err = 1;
#if 0
break;
#endif
}
}
if (firstsend && !Tmsgcnt && bang && !equals) {
/* we didn't transfer any messages, there seems to have been all
messages marked with '!', so we will re-scan */
if (Xtrace)
tcmdprintf ("XFWD: Relooping on .fwd file for %s - 1st scan since last aborted session\n", fwd_bbsname(m));
fwdunlockit (m->name);
goto checkloop;
}
/* one last check, to avoid deleting a file that JUST added a record */
if (isnewprivmail (m, "fwd") > 0) {
if(Xtrace)
tcmdprintf ("XFWD: Relooping on .fwd file for %s - new messages received\n", fwd_bbsname(m));
fwdunlockit (m->name);
goto checkloop;
}
(void) fclose (f->fwdfile);
if (!err)
(void) remove (name);
fwdunlockit (m->name);
kwait (NULL);
if (!Tmsgcnt)
/* We had no data. */
return 2;
return 1;
}
/* This is the main entry point for X-forwarding. */
int
doxfwd(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct fwd f;
struct mbx *m;
struct fbbpacket *msglst;
int i;
int firstsend = 1;
int Done;
int rc;
int FBBRdone = FALSE; /* Receiving system has no more data. */
int NeedData;
int X_fwd;
f.m = (struct mbx *)p;
m = f.m;
log (f.m->user, forwardingto, (argc) ? "Incom" : "Outgo", m->name);
/* First verify that this is a system that supports X-forwarding. */
if(!(f.m->sid & MBX_XFWD)) {
tputs ("Huh?\n");
usflush (m->user);
return -1;
}
/* Get memory for the msglst array. */
f.msglst = (struct fbbpacket *)callocw ((unsigned)XMAXMSGS, sizeof(struct fbbpacket));
m->msglst = msglst = f.msglst;
NeedData = FALSE;
Done = FALSE;
X_fwd = FALSE;
/* See if we were called because we received a SX from the remote system. */
if (!argc) {
f.m->state = MBX_FORWARD; /* We are in send mode. */
FBBRdone = FALSE;
NeedData = TRUE;
X_fwd = TRUE;
} else if(argv[0][0] == 'S' && m->stype == 'X') {
if (argc != 2) {
tputs ("Huh?\n");
usflush (m->user);
Done = TRUE;
} else {
f.numtrans = (char) atoi (argv[1]);
/* indicate that we are in receive mode. */
f.m->state = MBX_REVFWD;
FBBRdone = FALSE;
}
} else {
/* Must have received a F> from the remote system. */
f.m->state = MBX_FORWARD; /* We are in send mode. */
FBBRdone = TRUE;
}
if(Xtrace)
tcmdprintf ("XFWD: %sing forwarding started with %s.\n", (argc) ? "Incom" : "Outgo", fwd_bbsname(m));
while (!Done) {
kwait (NULL);
if (f.m->state == MBX_REVFWD) {
if (Xtrace)
tcmdprintf ("XFWD: Receiving data from %s.\n", fwd_bbsname(m));
if (NeedData) { /* null out the line. */
f.m->line[0] = 0;
f.numtrans = 0;
}
NeedData = TRUE;
/* Receive data from remote system. Process SX block. */
rc = doxrecv (&f);
if (rc == 4) { /* Remote system sent us a F> */
if (X_fwd)
Done = TRUE;
else /* Change status. */
f.m->state = MBX_FORWARD;
FBBRdone = TRUE;
} else if (rc)
Done = TRUE;
if (Done != TRUE) {
tputs ((X_fwd == TRUE) ? "F>\n" : ">\n");
if (Xtrace)
tcmdprintf ("XFWD: Sending '%s>' to %s\n",
(X_fwd == TRUE) ? "F" : "", fwd_bbsname(m));
usflush (m->user);
}
} else {
if (Xtrace)
tcmdprintf ("XFWD: Sending data to %s.\n", fwd_bbsname(m));
NeedData = FALSE;
/* Change status. */
rc = doxsend (&f, firstsend);
firstsend = 0;
if (rc == 3) /* An error occured. */
break;
if ((rc == 0) || (rc == 2)) {
/* We had no data for remote system. */
if (FBBRdone) {
/* They have no more data for us....
So we break out of this loop and disconnect.
*/
break;
} else {
/* Tell them that we do not have any data for them. */
if(Xtrace)
tcmdprintf (nodatatosend, fwd_bbsname(m));
tputs ("F>\n");
/* Change status. */
f.m->state = MBX_REVFWD;
usflush (m->user);
NeedData = TRUE;
}
}
}
} /* endwhile */
/* free anything in the msglst array. */
for (i = 0; i < XMAXMSGS ; i++) {
free (msglst[i].to);
free (msglst[i].from);
free (msglst[i].messageid);
free (msglst[i].sline);
msglst[i].to = msglst[i].from = msglst[i].messageid = msglst[i].sline = NULLCHAR;
}
/* Now free the msglst array. */
free (msglst);
usflush (m->user);
releasesubchannel (m); /* just in case */
if (X_fwd) {
exitfwd(m);
return 0;
} else {
/* This section marks the last fwd session time */
if ((i = indexFwdBbs (fwd_bbsname(m))) != NUMFWDBBS) {
MyFwds[i].laston = time (NULL);
MyFwds[i].lastactivity = time (NULL);
}
m->state = MBX_CMD;
return domboxbye(0,NULL,m);
}
}
#endif /* ifdef XFWD */